from distutils.command.clean import clean

from django import forms
from django.core.validators import RegexValidator
from web import models
from django.core.exceptions import ValidationError
from django.conf import settings
import random
from utils.tencent.sms import send_sms_single
from django_redis import get_redis_connection
from utils import encrypt
from web.forms.bootstrap import BootStrapForm

class RegisterModelForm(BootStrapForm,forms.ModelForm):

    password = forms.CharField(
        label='密码',
        min_length=8,
        max_length=64,
        error_messages={'min_length': '密码长度不能小于8字符',
                        'max_length': '密码长度不能大于64字符'
                        },
        widget=forms.PasswordInput())
    confirm_password = forms.CharField(
        label='重复密码',
        min_length=8,
        max_length=64,
        error_messages={'min_length': '重复密码长度不能小于8字符',
                        'max_length': '重复密码长度不能大于64字符'
                        },
        widget=forms.PasswordInput())

    mobile_phone = forms.CharField(
        label='手机号',
        validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$',
                                   '手机号格式错误'), ])

    code = forms.CharField(label='验证码',widget=forms.TextInput())
    class Meta:
        model = models.UserInfo
        fields = ['username','email','password','confirm_password','mobile_phone','code']
    # def __init__(self,*args,**kwargs):
    #     super().__init__(*args,**kwargs)
    #     for name,field in self.fields.items():
    #         field.widget.attrs['class'] = 'form-control'
    #         field.widget.attrs['placeholder'] = '请输入%s' %(field.label)
    def clean_username(self):
        username = self.cleaned_data['username']

        exists = models.UserInfo.objects.filter(username=username).exists()
        if exists:
            raise ValidationError('用户已存在')
        return username
    def clean_email(self):
        email = self.cleaned_data['email']

        exists = models.UserInfo.objects.filter(email=email).exists()
        if exists:
            raise ValidationError('邮箱已存在')
        return email

    def clean_password(self):
        pwd = self.cleaned_data['password']
        encrypt.md5(pwd)
        return pwd

    def clean_confirm_password(self):
        pwd = self.cleaned_data['password']
        confirm_pwd = self.cleaned_data['confirm_password']
        if pwd != confirm_pwd:
            raise ValidationError('两次输入的密码不一致')
        return confirm_pwd

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if exists:
            raise ValidationError('手机号已注册')
        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data['code']
        mobile_phone = self.cleaned_data['mobile_phone']
        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)
        if not redis_code:
            raise ValidationError('验证码不存在，或未发送')
        redis_str_code = str(redis_code.decode('utf-8'))
        if code.strip() != redis_str_code:
            raise ValidationError('验证码输入错误')
        return code
class SendSmsModel(forms.Form):
    mobile_phone = forms.CharField(label="手机号",validators=[RegexValidator(r'^1[3|4|5|6|7|8|9]\d{9}$','手机格式错误'),])

    def __init__(self,request,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.request = request
    def clean_mobile_phone(self):
        """手机号校验钩子"""
        mobile_phone = self.cleaned_data.get('mobile_phone')
        # 判断短信模板是否有问题
        tpl = self.request.GET.get('tpl')
        template_id = settings.TENCENT_SMS_TEMPLATE[tpl]
        if not template_id:
            raise ValidationError('短信模板错误')

        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if tpl == "login":
            if not exists:
                raise ValidationError('手机号不存在')
        else:
            # 校验数据库中是否已经有手机号
            if exists:
                raise ValidationError('手机号已存在')

        code = random.randrange(1000,9999)

        # 发送短信
        sms = send_sms_single(mobile_phone,template_id,[code,])
        if sms['result'] != 0:
            raise ValidationError('短信发送失败,{}'.format(sms['errmsg']))

        # 验证码写入redis(django-redis)
        conn = get_redis_connection()
        conn.set(mobile_phone,code,ex=60)

        return mobile_phone

class Login_SMS_Form(BootStrapForm,forms.Form):

    mobile_phone = forms.CharField(
        label='手机号',
        validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$',
                                   '手机号格式错误'), ])
    code = forms.CharField(label='验证码', widget=forms.TextInput())

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if not exists:
            raise ValidationError('手机号不存在')

        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data['code']
        mobile_phone = self.cleaned_data['mobile_phone']
        # 手机号不存在，则验证码无需再校验
        if not mobile_phone:
            return code

        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone  )
        if not redis_code:
            raise ValidationError('验证码不存在，或未发送')
        redis_str_code = str(redis_code.decode('utf-8'))
        if code.strip() != redis_str_code:
            raise ValidationError('验证码输入错误')
        return code

class LoginForm(BootStrapForm,forms.Form):
    username = forms.CharField(label="用户名")
    password = forms.CharField(label="密码",widget=forms.PasswordInput())
    code = forms.CharField(label="图片验证码")

    def __init__(self,request,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.request = request
    def clean_code(self):
        '''钩子，图片验证码是否正确'''
        # 读取用户输入的图片验证码
        code = self.cleaned_data['code']

        # 去session中获取图片验证码
        session_code = self.request.session.get('image_code')
        if not session_code:
            raise ValidationError("验证码已过期，请重新获取")

        if code.strip().upper() != session_code.strip().upper():
            raise ValidationError("验证码输入错误")
        return code

    def clean_password(self):
        pwd = self.cleaned_data['password']
        return encrypt.md5(pwd)


